/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package deatax;

import deatax.mode.GameMode;
import deatax.card.Card;
import deatax.card.CardEffect;
import deatax.card.CardManager;
import deatax.display.BoardRenderer;
import deatax.display.Camera;
import deatax.display.GUI;
import deatax.display.miniboard.MiniBoard;
import deatax.display.miniboard.MiniBoardTile;
import deatax.mode.CivilisationGameMode;
import deatax.mode.DominationGameMode;
import deatax.mode.EliminationGameMode;
import deatax.state.GameState;
import deatax.unit.Unit;
import java.awt.BorderLayout;
import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;

/**
 *
 * @author pson
 */
public class GameDataController {

    GameData data;
    HashMap<String, GameMode> modes;
    public static final int RESOURCE = 1;
    public static final int IMPROVE = 2;
    public static final int IMPROVE_COST = 3;
    public static final int IMPROVE_BONUS = 4;
    public static final int IMPROVE_UP = 5;
    public static final int TERRAIN = 6;
    public static final int TERRAIN_BONUS = 7;
    public static final int TERRAIN_UP = 8;
    public static final int LANDMASS = 9;
    public static final int SETTLEMENT = 10;
    public static final int UNIT = 11;
    public static final int UNIT_SKILL = 12;
    public static final int ROAD = 13;
    public static final int IMPROVE_BUILD = 14;
    public static final int UNIT_COST = 15;
    public static final int RESOURCE_TAG = 16;
    public static final int CARD = 1;
    public static final int EFFECT = 2;
    public static final int CARD_EFFECT = 3;

    public GameDataController(GameData data) {
        this.data = data;
        data.setGame(new GameManager());
        try {
            //this.loadCFG(Main.class.getResourceAsStream("tiles.cfg"), data.getGame());
            this.loadCFG(ResourceLoader.loadStream("tiles.cfg"), data.getGame());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        modes = new HashMap<String, GameMode>();
        modes.put("Domination", new DominationGameMode(data));
        modes.put("Elimination", new EliminationGameMode(data));
        modes.put("Civilisation", new CivilisationGameMode(data));
        
    }
    
    
    public GameMode getMode(String string) {
        return modes.get(string);
    }

    public void loadMini(InputStream in, MiniBoard board) throws FileNotFoundException, IOException {
        BufferedReader fr = new BufferedReader(new InputStreamReader(in));
        //int context = -1;
        String line = fr.readLine();
        while (line != null) {
            line = line.trim();
            if (!(line.isEmpty() || line.startsWith(";"))) {
                try {
                    String[] arg = line.split(":");
                    //System.out.println(line);
                    board.addTile(new MiniBoardTile(Integer.parseInt(arg[0]), Integer.parseInt(arg[1]), arg[2],board));
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            line = fr.readLine();
        }
    }

    public void loadCards(InputStream in, CardManager card) throws FileNotFoundException, IOException {
        BufferedReader fr = new BufferedReader(new InputStreamReader(in));
        int context = -1;
        String line = fr.readLine();
        while (line != null) {
            line = line.trim();

            if (line.equals("|card")) {
                context = CARD;
            } else if (line.equals("|effect")) {
                context = EFFECT;
            } else if (line.equals("|card_effect")) {
                context = CARD_EFFECT;
            } else if (!(line.isEmpty() || line.startsWith(";"))) {
                try {
                    switch (context) {
                        case CARD: {
                            String[] arg = line.split(":");
                            int num = Integer.parseInt(arg[3]);
                            Card c = new Card(arg[0], arg[1], arg[2], num);
                            card.addCard(arg[0], c);
                        }
                        break;
                        case EFFECT: {
                            String[] arg = line.split(":");
                            card.addEffect(arg[0], (CardEffect) Main.class.getClassLoader().loadClass("deatax.card.Card" + arg[0]).newInstance());
                        }
                        break;
                        case CARD_EFFECT: {
                            String[] arg = line.split(":");
                            if (arg.length > 1) {
                                CardEffect ce = card.getEffects().get(arg[1]);
                                String[] ca = new String[arg.length - 2];
                                for (int i = 0; i < arg.length - 2; ++i) {
                                    ca[i] = arg[i + 2];
                                }
                                card.get(arg[0]).addEffect(ce, ca);
                            }
                        }
                        break;
                        default:
                            break;
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            line = fr.readLine();
        }

    }

    public void loadCFG(InputStream in, GameManager game) throws FileNotFoundException, IOException {
        //File f = new File(filename);
        BufferedReader fr = new BufferedReader(new InputStreamReader(in));
        int context = -1;
        String context2 = null;


        String line = fr.readLine();
        while (line != null) {
            line = line.trim();
            //System.out.println(line);
            if (line.equals("|resource")) {
                context = RESOURCE;
            } else if (line.equals("|resource_tag")) {
                context = RESOURCE_TAG;
            } else if (line.equals("|improve")) {
                context = IMPROVE;
            } else if (line.equals("|settlement")) {
                context = SETTLEMENT;
            } else if (line.equals("|road")) {
                context = ROAD;
            } else if (line.equals("|improve_bonus")) {
                context = IMPROVE_BONUS;
            } else if (line.equals("|improve_cost")) {
                context = IMPROVE_COST;
            } else if (line.equals("|improve_up")) {
                context = IMPROVE_UP;
            } else if (line.equals("|terrain")) {
                context = TERRAIN;
            } else if (line.equals("|terrain_bonus")) {
                context = TERRAIN_BONUS;
            } else if (line.equals("|terrain_up")) {
                context = TERRAIN_UP;
            } else if (line.equals("|unit")) {
                context = UNIT;
            } else if (line.equals("|unit_cost")) {
                context = UNIT_COST;
            } else if (line.equals("|unit_skill")) {
                context = UNIT_SKILL;
            } else if (line.equals("|improve_build")) {
                context = IMPROVE_BUILD;
            } else if (line.startsWith("|landmass:")) {
                context = LANDMASS;
                context2 = line.substring(10);
                game.addLandmass(context2, new Landmass(context2));
            } else if (!(line.isEmpty() || line.startsWith(";"))) {

                try {
                    switch (context) {
                        case RESOURCE: {
                            String[] arg = line.split(":");
                            Resource r = new Resource(arg[0], Integer.parseInt(arg[1]));
                            game.addResource(arg[0], r);
                        }
                        break;
                        case RESOURCE_TAG: {
                            String[] arg = line.split(":");
                            game.getResource(arg[0]).addTag(arg[1]);
                        }
                        break;
                        case IMPROVE: {
                            String[] arg = line.split(":");
                            Improvement i = new Improvement(arg[0], Integer.parseInt(arg[1]));
                            game.addImprove(arg[0], i);
                        }
                        break;
                        case SETTLEMENT: {
                            String[] arg = line.split(":");
                            Settlement s = new Settlement(arg[0], Integer.parseInt(arg[1]), 
                                    Integer.parseInt(arg[2]), Integer.parseInt(arg[3]), 
                                    Integer.parseInt(arg[4]), Integer.parseInt(arg[5]), 
                                    Integer.parseInt(arg[6]), Integer.parseInt(arg[7]));
                            game.addImprove(arg[0], s);
                        }
                        break;
                        case ROAD: {
                            String[] arg = line.split(":");
                            Road r = new Road(arg[0], Integer.parseInt(arg[1]), Integer.parseInt(arg[2]), Integer.parseInt(arg[3]));
                            game.addImprove(arg[0], r);
                        }
                        break;
                        case IMPROVE_BONUS: {
                            String[] arg = line.split(":");
                            game.getImprove(arg[0]).addBonus(game.getResource(arg[1]), Integer.parseInt(arg[2]));
                        }
                        break;
                        case IMPROVE_COST: {
                            String[] arg = line.split(":");
                            game.getImprove(arg[0]).addCost(game.getResource(arg[1]), Integer.parseInt(arg[2]));
                        }
                        break;
                        case IMPROVE_UP: {
                            String[] arg = line.split(":");
                            game.getImprove(arg[0]).addUpgrades(game.getImprove(arg[1]));
                        }
                        break;
                        case TERRAIN: {
                            String[] arg = line.split(":");
                            Terrain t = new Terrain(arg[0], Integer.parseInt(arg[1]), Integer.parseInt(arg[2]), Integer.parseInt(arg[3]));
                            game.addTerrain(arg[0], t);
                        }
                        break;
                        case TERRAIN_BONUS: {
                            String[] arg = line.split(":");
                            game.getTerrain(arg[0]).addBonus(game.getResource(arg[1]), Integer.parseInt(arg[2]));
                        }
                        break;
                        case TERRAIN_UP: {
                            String[] arg = line.split(":");
                            game.getTerrain(arg[0]).addImprovement(game.getImprove(arg[1]));
                        }
                        break;
                        case LANDMASS: {
                            String[] arg = line.split(":");
                            game.getLandmass(context2).addCondition(game.getTerrain(arg[0]), Integer.parseInt(arg[1]));
                        }
                        break;
                        case UNIT: {
                            String[] arg = line.split(":");
                            game.addUnit(arg[0], new Unit(arg[0], Integer.parseInt(arg[1]), Integer.parseInt(arg[2]), Integer.parseInt(arg[3])));
                        }
                        break;
                        case UNIT_COST: {
                            String[] arg = line.split(":");
                            game.getUnit(arg[0]).addCost(game.getResource(arg[1]), Integer.parseInt(arg[2]));
                        }
                        break;
                        case UNIT_SKILL: {
                            String[] arg = line.split(":");
                            game.getUnit(arg[0]).addSkill(arg[1]);
                        }
                        break;
                        case IMPROVE_BUILD: {
                            String[] arg = line.split(":");
                            Improvement i = game.getImprove(arg[0]);
                            i.addUnit(game.getUnit(arg[1]));
                        }
                        break;
                        default:
                            break;

                    }
                } catch (Exception ex) {
                    System.err.println("Current args: " + line);
                    ex.printStackTrace();
                }
            }
            line = fr.readLine();
        }
    }

    public void changeGameState(String state) {
        data.getState().popState();
        data.getState().pushState(state);
    }

    public void changeGameState(GameState state) {
        data.getState().popState();
        data.getState().pushState(state);
    }

    public void pushGameState(String state) {
        data.getState().pushState(state);
    }

    public void pushGameState(GameState state) {
        data.getState().pushState(state);
    }

    public void popGameState() {
        data.getState().popState();
    }

    public void addPlayer(String name, Color color) {
        if (data.getRoster() == null) {
            data.setRoster(new PlayerRoster());
        }
        data.getRoster().addPlayer(new Player(data, name, color));
    }

    public void setMapParams(int seed, String l, int size) {
        RNG.seed(seed);
        data.setMap(new Map(data.getGame().getLandmass(l), data, 100, 100));
        data.getMap().seed(1, size);
        data.setDice(new Dice(2, 6));
    }

    public void setSelf(int n) {
        System.out.println("SeTTIING self toL " + n);
        if (n < 0) {
            data.setSelf(null);
        } else {
            data.setSelf(data.getRoster().getPlayers().get(n));
        }
    }

    public void setGameMode(String in) {
        GameMode gm;
        String[] arg = in.split(";");
        String mode = arg[0];
        gm = modes.get(mode);
        if (arg.length > 1) {
            gm.setArgs(arg);
        }
        gm.setOnline(data.getSelf() != null);
        
        for (Player p : data.getRoster().getPlayers()) {
            p.addResourceListener(gm);
            p.addLandListener(gm);
            p.addPopulationListener(gm);
        }
        data.setMode(gm);
    }
    public JFrame getFrame() {
        return data.getFrame();
    }

    public void beginGame() {
        GLCapabilities glc = new GLCapabilities(null);
        
        glc.setDoubleBuffered(true);
        GLCanvas canvas =new GLCanvas(glc);
//        canvas.set
        data.setDisplay(new GLCanvas(glc));
        data.setRender(new BoardRenderer(data));
        data.setCamera(new Camera(data));
        data.getGame().calculate_bases();
        data.setCards(new CardManager());

        try {
            this.loadCards(ResourceLoader.loadStream("cards.cfg"), data.getCards());
            //loadCards(Main.class.getResourceAsStream("cards.cfg"), data.getCards());
        } catch (IOException ex) {
        }


        data.setMiniboard(new MiniBoard(data));

        try {
            this.loadMini(ResourceLoader.loadStream("mini.cfg"), data.getMiniboard());
            //loadMini(Main.class.getResourceAsStream("mini.cfg"), data.getMiniboard());
        } catch (IOException ex) {

        }
        data.getMiniboard().init();
        data.getFrame().getContentPane().add(data.getDisplay(), BorderLayout.CENTER);
        data.setGui(new GUI(data));
        data.getDisplay().addGLEventListener(data);
        data.start();
        data.getGui().gameStart();
        data.getFrame().validate();
        data.setTray(new TrayMenu(data));
    }


    

}
